package com.snow.vpnclient.util;

import android.content.Context;

import androidx.datastore.preferences.core.MutablePreferences;
import androidx.datastore.preferences.core.Preferences;
import androidx.datastore.preferences.core.PreferencesKeys;
import androidx.datastore.preferences.rxjava3.RxPreferenceDataStoreBuilder;
import androidx.datastore.rxjava3.RxDataStore;

import com.blankj.utilcode.util.ToastUtils;

import io.reactivex.rxjava3.core.Flowable;
import io.reactivex.rxjava3.core.Single;

/**
 * @author liufq
 * @since 2022-10-27 11:01:35
 */
public enum DataStoreHelper {

    INSTANCE;

    private RxDataStore<Preferences> dataStore;

    public void getPreferences(Context context, String dataFileName) {
        RxPreferenceDataStoreBuilder builder = new RxPreferenceDataStoreBuilder(context, dataFileName);
        dataStore = builder.build();
    }

    /**
     * 写入值
     */
    public void set(String strKey, Object value) {
        if (value == null) {
            return;
        }
        if (value instanceof Integer) {
            Preferences.Key<Integer> intKey = PreferencesKeys.intKey(strKey);
            dataStore.updateDataAsync(preferences -> {
                MutablePreferences mutablePreferences = preferences.toMutablePreferences();
                mutablePreferences.set(intKey, (Integer) value);
                return Single.just(mutablePreferences);
            });
        } else if (String.class.equals(value.getClass())) {
            Preferences.Key<String> stringKey = PreferencesKeys.stringKey(strKey);
            dataStore.updateDataAsync(preferences -> {
                        MutablePreferences mutablePreferences = preferences.toMutablePreferences();
                        mutablePreferences.set(stringKey, (String) value);
                        return Single.just(mutablePreferences);
                    }
            );
        } else if (Boolean.class.equals(value.getClass())) {
            Preferences.Key<Boolean> booleanKey = PreferencesKeys.booleanKey(strKey);
            dataStore.updateDataAsync(preferences -> {
                MutablePreferences mutablePreferences = preferences.toMutablePreferences();
                mutablePreferences.set(booleanKey, (Boolean) value);
                return Single.just(mutablePreferences);
            });
        } else if (Double.class.equals(value.getClass())) {
            Preferences.Key<Double> doubleKey = PreferencesKeys.doubleKey(strKey);
            dataStore.updateDataAsync(preferences -> {
                MutablePreferences mutablePreferences = preferences.toMutablePreferences();
                mutablePreferences.set(doubleKey, (Double) value);
                return Single.just(mutablePreferences);
            });
        } else if (Float.class.equals(value.getClass())) {
            Preferences.Key<Float> floatKey = PreferencesKeys.floatKey(strKey);
            dataStore.updateDataAsync(preferences -> {
                MutablePreferences mutablePreferences = preferences.toMutablePreferences();
                mutablePreferences.set(floatKey, (Float) value);
                return Single.just(mutablePreferences);
            });
        } else if (Long.class.equals(value.getClass())) {
            Preferences.Key<Long> longKey = PreferencesKeys.longKey(strKey);
            dataStore.updateDataAsync(preferences -> {
                MutablePreferences mutablePreferences = preferences.toMutablePreferences();
                mutablePreferences.set(longKey, (Long) value);
                return Single.just(mutablePreferences);
            });
        } else {
            ToastUtils.showShort("无效值异常, " + value);
        }
    }

    /**
     * 读取DataStore值
     */
    public String getString(String strKey) {
        try {
            Preferences.Key<String> stringKey = PreferencesKeys.stringKey(strKey);
            Flowable<String> flowable = dataStore.data().map(preferences -> preferences.get(stringKey));
            return flowable.blockingFirst();
        } catch (Exception e) {
            Logger.e("DataStore获取数据失败，key = " + strKey);
            return null;
        }
    }

    public Integer getInteger(String strKey) {
        Preferences.Key<Integer> key = PreferencesKeys.intKey(strKey);
        Flowable<Integer> flowable = dataStore.data().map(preferences -> preferences.get(key));
        return flowable.blockingFirst();
    }

    public Long getLong(String strKey) {
        Preferences.Key<Long> key = PreferencesKeys.longKey(strKey);
        Flowable<Long> flowable = dataStore.data().map(preferences -> preferences.get(key));
        return flowable.blockingFirst();
    }

    public Boolean getBoolean(String strKey) {
        try {
            Preferences.Key<Boolean> key = PreferencesKeys.booleanKey(strKey);
            Flowable<Boolean> booleanFlowable = dataStore.data().map(preferences -> preferences.get(key));
            return booleanFlowable.blockingFirst();
        } catch (Exception e) {
            Logger.e("DataStore获取数据失败，key = " + strKey);
            return false;
        }
    }

    /***
     *
     * @param strKey
     * @return 返回 Float 类型值
     */
    public Float readValueBackFloat(String strKey) {
        Preferences.Key<Float> keys = PreferencesKeys.floatKey(strKey);
        Flowable<Float> floatFlowable = dataStore.data().map(preferences -> {
            return preferences.get(keys);
        });
        return floatFlowable.blockingFirst();
    }

    /***
     *
     * @param strKey
     * @return 返回 Double 类型值
     */
    public Double readValueBackDouble(String strKey) {
        Preferences.Key<Double> key = PreferencesKeys.doubleKey(strKey);
        Flowable<Double> flowable = dataStore.data().map(preferences -> {
            return preferences.get(key);
        });
        return flowable.blockingFirst();
    }

    /***
     *
     * @param strKey
     * @return 返回 Long 类型值
     */
    public Long readValueBackLong(String strKey) {
        Preferences.Key<Long> key = PreferencesKeys.longKey(strKey);
        Flowable<Long> flowable = dataStore.data().map(preferences -> {
            return preferences.get(key);
        });
        return flowable.blockingFirst();
    }
}
